home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / VAPOR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  9.9 KB  |  377 lines

  1. #include <math.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <GL/glut.h>
  6. #include "texture.h"
  7.  
  8. /* Some <math.h> files do not define M_PI... */
  9. #ifndef M_PI
  10. #define M_PI 3.14159265358979323846
  11. #endif
  12.  
  13. #ifndef __sgi
  14. /* Most math.h's do not define float versions of the trig functions. */
  15. #define sinf sin
  16. #define cosf cos
  17. #define atan2f atan2
  18. #endif
  19.  
  20.  
  21. /* taken from skyfly */
  22. static float paper_plane_vertexes[] = {
  23. /*Nx  Ny  Nz   Vx     Vy    Vz */
  24. /* ----------------------------    Top view of plane, middle stretched open  */
  25.  0.2, 0., .98, -.10,    0,  .02,/* vertex #'s      4 (.48,0,-.06)            */
  26.  0., 0., 1.,   -.36,  .20, -.04,/*                 .                         */
  27.  0., 0., 1.,    .36,  .01,    0,/*                ...                        */
  28.  0., 0.,-1.,   -.32,  .02,    0,/*                 .             +X          */
  29.  0., 1., 0.,    .48,    0, -.06,/*               2 . 6,8          ^          */
  30.  0., 1., 0.,   -.30,    0, -.12,/*               . . .            |          */
  31.  0.,-1., 0.,    .36, -.01,    0,/*              .. . ..           |          */
  32.  0.,-1., 0.,   -.32, -.02,    0,/*               . . .            |          */
  33.  0., 0.,-1.,    .36, -.01,    0,/*             . . . . .  +Y<-----*          */
  34.  0., 0.,-1.,   -.36, -.20, -.04,/*               . . .     for this picture  */
  35.  -0.2, 0., .98,  -.10,  0,  .02,/*            .  . . .  .  coord system rot. */
  36.  -0.2, 0., -.98, -.10,  0,  .02,/*               . . .     90 degrees        */
  37.  0., 0., -1.,  -.36,  .20, -.04,/*           .   . . .   .                   */
  38.  0., 0., -1.,   .36,  .01,    0,/*               . # .           # marks     */
  39.  0., 0., 1.,   -.32,  .02,    0,/*          .    . . .    .   (0,0) origin   */
  40.  0., -1., 0.,   .48,    0, -.06,/*               . . .         (z=0 at top   */
  41.  0., -1., 0.,  -.30,    0, -.12,/*         .     0 . 10    .    of plane)    */
  42.  0.,1., 0.,     .36, -.01,    0,/*             . . . . .                     */
  43.  0.,1., 0.,    -.32, -.02,    0,/*        .  .   . . .   .  .                */
  44.  0., 0.,1.,     .36, -.01,    0,/*         .     . . .     .                 */
  45.  0., 0.,1.,    -.36, -.20, -.04,/*       1.......3.5.7.......9               */
  46.  0.2, 0., -.98,  -.10,  0,  .02,/* (-.36,.2,-.04)                            */
  47. };
  48.  
  49. #define MAX_TIME    (2*196)
  50. #define MAX_VAPOR    1024
  51. int vapors = 0;
  52. static struct vapor {
  53.     float x, y, z;
  54.     int time;
  55.     float size;
  56. } vapor[MAX_VAPOR];
  57.  
  58. static float ttrans[2];
  59. static float scale = 1.;
  60. static float transx, transy, rotx, roty;
  61. static int ox = -1, oy = -1;
  62. static int show_t = 0;
  63. static int mot;
  64. #define PAN    1
  65. #define ROT    2
  66.  
  67. static int _time = 1;
  68. static float _x = -1.;
  69. static float _y = .75;
  70.  
  71. void
  72. pan(int x, int y) {
  73.     transx +=  (x-ox)/500.;
  74.     transy -= (y-oy)/500.;
  75.     ox = x; oy = y;
  76.     glutPostRedisplay();
  77. }
  78.  
  79. void
  80. rotate(int x, int y) {
  81.     rotx += x-ox;
  82.     if (rotx > 360.) rotx -= 360.;
  83.     else if (rotx < -360.) rotx += 360.;
  84.     roty += y-oy;
  85.     if (roty > 360.) roty -= 360.;
  86.     else if (roty < -360.) roty += 360.;
  87.     ox = x; oy = y;
  88.     glutPostRedisplay();
  89. }
  90.  
  91. void
  92. motion(int x, int y) {
  93.     if (mot == PAN) pan(x, y);
  94.     else if (mot == ROT) rotate(x,y);
  95. }
  96.  
  97. void
  98. mouse(int button, int state, int x, int y) {
  99.     if(state == GLUT_DOWN) {
  100.     switch(button) {
  101.     case GLUT_LEFT_BUTTON:
  102.         mot = PAN;
  103.         motion(ox = x, oy = y);
  104.         break;
  105.     case GLUT_MIDDLE_BUTTON:
  106.         mot = ROT;
  107.         motion(ox = x, oy = y);
  108.         break;
  109.     case GLUT_RIGHT_BUTTON:
  110.         break;
  111.     }
  112.     } else if (state == GLUT_UP) {
  113.     mot = 0;
  114.     }
  115. }
  116.  
  117. void toggle_t(void) {
  118.     show_t ^= 1;
  119. }
  120.  
  121. void wire(void) {
  122.     static int w;
  123.     if (w ^= 1)
  124.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  125.     else
  126.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  127. }
  128.  
  129. void light(void) {
  130.     static int l;
  131.     if (l ^= 1)
  132.     glEnable(GL_LIGHTING);
  133.     else
  134.     glDisable(GL_LIGHTING);
  135. }
  136.  
  137. void up(void) { scale += .1; }
  138. void down(void) { scale -= .1; }
  139.  
  140. void
  141. draw_plane(void) {
  142.     glEnable(GL_LIGHTING);
  143.     glShadeModel(GL_FLAT);
  144.     glRotatef(-120.f, 1.f, 0.f, 0.f);
  145. #define nv(p) glNormal3fv(paper_plane_vertexes+6*p); glVertex3fv(paper_plane_vertexes+6*p+3)
  146.     glEnable(GL_CULL_FACE);
  147.     glCullFace(GL_FRONT);
  148.     glBegin(GL_TRIANGLE_STRIP);
  149.     nv(0); nv(1); nv(2); nv(3); nv(4); nv(5); nv(6); nv(7); nv(8); nv(9); nv(10);
  150.     glEnd();
  151.     glCullFace(GL_BACK);
  152.     glBegin(GL_TRIANGLE_STRIP);
  153.     nv(11); nv(12); nv(13); nv(14); nv(15); nv(16); nv(17); nv(18); nv(19); nv(20); nv(21);
  154.     glEnd();
  155.     glDisable(GL_CULL_FACE);
  156.     glShadeModel(GL_SMOOTH);
  157.     glDisable(GL_LIGHTING);
  158. #undef nv
  159. }
  160.  
  161. void
  162. add_vapor(void) {
  163.     int i;
  164.     /* garbage collect */
  165.     for(i = 0; i < vapors; i++)
  166.     if (_time - vapor[i].time > MAX_TIME) {
  167.         memcpy(vapor+i, vapor+i+1, (vapors-i-1)*sizeof vapor[0]);
  168.         vapors--;
  169.     }
  170.     if (vapors >= MAX_VAPOR) {
  171.     printf("max_vapors\n");
  172.     return;
  173.     }
  174.     vapor[vapors].time = _time;
  175.     vapor[vapors].x = -.6f + _x;
  176.     vapor[vapors].y = _y;
  177.     vapor[vapors].z = 0.f;
  178.     vapor[vapors].size = 1.f;
  179.     vapors++;
  180.     if (_x > 8.5) {
  181.     _y = .75f;
  182.     _x = -2.f;
  183.     vapors = 0;
  184.     }
  185. }
  186.  
  187. void
  188. animate(void) {
  189.     static int cnt = 0;
  190.     ttrans[0] += .01;
  191.     if (ttrans[0] == 1.0) ttrans[0] = 0;
  192.     ttrans[1] += .005;
  193.     if (ttrans[1] == 1.0) ttrans[1] = 0;
  194.     _y -= .01f;
  195.     _x +=.025f;
  196.     if (cnt++ & 1) add_vapor();
  197.     _time++;
  198.     glutPostRedisplay();
  199. }
  200.  
  201. void help(void) {
  202.     printf("Usage: vapor [image]\n");
  203.     printf("'h'            - help\n");
  204.     printf("'l'            - toggle lighting\n");
  205.     printf("'t'            - toggle wireframe\n");
  206.     printf("'UP'           - scale up\n");
  207.     printf("'DOWN'         - scale down\n");
  208.     printf("left mouse     - pan\n");
  209.     printf("middle mouse   - rotate\n");
  210. }
  211.  
  212. void init(char *filename) {
  213.     static GLfloat plane_mat[] = { 1.f, 1.f, .2f, 1.f };
  214.     static unsigned *image;
  215.     static int width, height, components, i;
  216.     if (filename) {
  217.     image = read_texture(filename, &width, &height, &components);
  218.     if (image == NULL) {
  219.         fprintf(stderr, "Error: Can't load image file \"%s\".\n",
  220.             filename);
  221.         exit(EXIT_FAILURE);
  222.     } else {
  223.         printf("%d x %d image loaded\n", width, height);
  224.     }
  225.     if (components != 2 && components != 4) {
  226.         printf("must be an rgba or la image\n");
  227.         exit(EXIT_FAILURE);
  228.     }
  229.     for(i = 0; i < width*height; i++)
  230.         image[i] = image[i] | 0xffffff00;
  231.     } else {
  232.     int i, j;
  233.     unsigned char *img;
  234.     components = 4; width = height = 512;
  235.     image = (unsigned *) malloc(width*height*sizeof(unsigned));
  236.     img = (unsigned char *)image;
  237.     for (j = 0; j < height; j++)
  238.         for (i = 0; i < width; i++) {
  239.         int w2 = width/2, h2 = height/2;
  240.         if (i & 32)
  241.             img[4*(i+j*width)+0] = 0xff;
  242.         else
  243.             img[4*(i+j*width)+1] = 0xff;
  244.         if (j&32)
  245.             img[4*(i+j*width)+2] = 0xff;
  246.         if ((i-w2)*(i-w2) + (j-h2)*(j-h2) > 64*64 &&
  247.             (i-w2)*(i-w2) + (j-h2)*(j-h2) < 300*300) img[4*(i+j*width)+3] = 0xff;
  248.         }
  249.  
  250.     }
  251.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  252.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  253.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  254.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  255.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  256.     glTexImage2D(GL_TEXTURE_2D, 0, components, width,
  257.                  height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
  258.     glEnable(GL_TEXTURE_2D);
  259.     glMatrixMode(GL_PROJECTION);
  260.     glLoadIdentity();
  261.     gluPerspective(50.,1.,.1,10.);
  262.     glMatrixMode(GL_MODELVIEW);
  263.     glLoadIdentity();
  264.     glTranslatef(0.,0.,-5.5);
  265.  
  266.     glEnable(GL_LIGHT0);
  267.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, plane_mat);
  268.  
  269.     glClearColor(0.1, 0.1, 0.6, 1.0);
  270.     glEnable(GL_BLEND);
  271.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  272.     glEnable(GL_ALPHA_TEST);
  273.     glAlphaFunc(GL_GREATER, 0./255.);
  274.  
  275.     glEnable(GL_DEPTH_TEST);
  276. }
  277.  
  278. void
  279. draw_vapor(void) {
  280.     int i;
  281.     float intensity = .9f;
  282.     float t;
  283.     struct vapor *v;
  284.  
  285.     glDepthMask(0);
  286.     glEnable(GL_TEXTURE_2D);
  287.  
  288.     for(i = 0; i < vapors; i++) {
  289.     v = vapor+i;
  290.     t = _time - v->time;
  291.  
  292.     glPushMatrix();
  293.     glTranslatef(v->x, v->y, v->z);
  294.     glScalef(.5*(t+40)/MAX_TIME, .5*(t+40)/MAX_TIME, 1.);
  295.     glColor4f(intensity,intensity,intensity,10./(t+0.f));
  296.     glBegin(GL_QUADS);
  297.     glTexCoord2f(0, 0); glVertex3f(-1., -1., -0.);
  298.     glTexCoord2f(0, 1); glVertex3f(-1., 1.,  0.);
  299.     glTexCoord2f(1, 1); glVertex3f( 1., 1.,  0.);
  300.     glTexCoord2f(1, 0); glVertex3f( 1., -1., -0.);
  301.     glEnd();
  302.     if (show_t) {
  303.         glDisable(GL_TEXTURE_2D);
  304.         glColor4f(0.,0.,0.,1.0);
  305.         glBegin(GL_LINE_LOOP);
  306.         glVertex3f(-1., -1., -0.);
  307.         glVertex3f(-1., 1.,  0.);
  308.         glVertex3f( 1., 1.,  0.);
  309.         glVertex3f( 1., -1., -0.);
  310.         glEnd();
  311.         glEnable(GL_TEXTURE_2D);
  312.     }
  313.     glPopMatrix();
  314.     }
  315.     glDisable(GL_TEXTURE_2D);
  316.     glDepthMask(1);
  317. }
  318.  
  319. void display(void) {
  320.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  321.     glPushMatrix();
  322.     glPushMatrix();
  323.     glColor4f(1.f,1.f,.2f,1.f);
  324.     glTranslatef(_x, _y+.05f, 0.f);
  325.     glScalef(2.f,2.f,2.f);
  326.     glRotatef(-10.f, 0.f, 0.f, 1.f);
  327.     draw_plane();
  328.     glPopMatrix();
  329.     draw_vapor();
  330.     glPopMatrix();
  331.     glutSwapBuffers();
  332. }
  333.  
  334. void reshape(int w, int h) {
  335.     glViewport(0, 0, w, h);
  336. }
  337.  
  338. /*ARGSUSED1*/
  339. void
  340. key(unsigned char key, int x, int y) {
  341.     switch(key) {
  342.     case 'l': light(); break;
  343.     case 't': toggle_t(); break;
  344.     case 'w': wire(); break;
  345.     case 'h': help(); break;
  346.     case '\033': exit(EXIT_SUCCESS); break;
  347.     default: break;
  348.     }
  349.     glutPostRedisplay();
  350. }
  351.  
  352. /*ARGSUSED1*/
  353. void
  354. special(int key, int x, int y) {
  355.     switch(key) {
  356.     case GLUT_KEY_UP:    up(); break;
  357.     case GLUT_KEY_DOWN:    down(); break;
  358.     }
  359. }
  360.  
  361. int main(int argc, char** argv) {
  362.     glutInitWindowSize(256, 256);
  363.     glutInit(&argc, argv);
  364.     glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
  365.     (void)glutCreateWindow(argv[0]);
  366.     init(argc == 1 ? "data/smoke.la" : argv[1]);
  367.     glutDisplayFunc(display);
  368.     glutKeyboardFunc(key);
  369.     glutSpecialFunc(special);
  370.     glutReshapeFunc(reshape);
  371.     glutMouseFunc(mouse);
  372.     glutMotionFunc(motion);
  373.     glutIdleFunc(animate);
  374.     glutMainLoop();
  375.     return 0;
  376. }
  377.